from typing import List
from dataclasses import dataclass, field
from .common_meta_info import CommonTableMetaInfo, CommonColumnMetaInfo, create_common_meta_info
from .sql_table_info import TableInfoSQL, TableInfoConfig
from src.base import camel_case_filter

# 映射 SQL 类型到 TypeScript 类型的函数
def map_sql_to_typescript_type(sql_type: str) -> str:
    # 将 SQL 类型转为大写，以便统一处理
    sql_type_upper = sql_type.upper()

    # 按前缀长度排序的类型映射规则，从长到短
    type_prefix_mapping = {
        'MEDIUMINT': 'number',
        'TIMESTAMP': 'string',  # 长前缀，确保优先匹配
        'DATETIME': 'string',
        'DATE': 'string',
        'TIME': 'string',  # 前端一般处理成字符串
        'SMALLINT': 'number',
        'TINYINT': 'number',
        'BIGINT': 'number',
        'DECIMAL': 'number',
        'INTEGER': 'number',
        'BOOLEAN': 'boolean',  # 优先匹配 BOOLEAN，避免被 BIT 覆盖
        'VARCHAR': 'string',
        'CHAR': 'string',
        'DOUBLE': 'number',
        'FLOAT': 'number',
        'BIT': 'boolean',
        'INT': 'number',  # 短前缀，需放在最后避免覆盖
        'TEXT': 'string',
        'BLOB': 'any',  # 前端用 any 表示二进制数据
        'REAL': 'number',  # 兼容 SQLite 中的 REAL 类型
        'NUMERIC': 'number',  # 高精度数字类型
        'ENUM': 'string',  # 枚举类型映射为 string
        'SET': 'string',  # 集合类型映射为 string
        # 可以添加更多映射规则...
    }

    # 遍历类型前缀映射规则，找到匹配的前缀
    for prefix, typescript_type in type_prefix_mapping.items():
        if sql_type_upper.startswith(prefix):
            return typescript_type

    # 默认返回 any
    return 'any'

# 用于生成 React 代码的列元信息
@dataclass
class ReactColumnMetaInfo(CommonColumnMetaInfo):
    typescript_type_name: str = field(init=False)  # 将 typescript_type_name 作为类变量，并在初始化时设置
    typescript_name: str = field(init=False)

    def __post_init__(self):
        # 初始化时根据 SQL 类型设置 TypeScript 类型
        self.typescript_type_name = map_sql_to_typescript_type(self.sql_raw_info.type)
        if (self.config.nullable):
            self.typescript_type_name += " | null"

        self.typescript_name = camel_case_filter(self.sql_raw_info.name)

    def __str__(self) -> str:
        return (
            f"ReactColumnMetaInfo: "
            f"字段名 (SQL): {self.sql_raw_info.name} ｜ "
            f"字段类型 (SQL): {self.sql_raw_info.type} ｜ "
            f"Java 类型: {self.typescript_type_name} ｜ "
            f"字段中文名: {self.config.chinese_name} ｜ "
            f"是否显示: {'显示' if self.config.column_show else '隐藏'}"
        )

# 用于生成 React 代码的表元信息
@dataclass
class ReactTableMetaInfo(CommonTableMetaInfo):
    primary_key_name: str = ''  # 主键字段名
    primary_key_type: str = ''  # 主键字段类型
    primary_keys: List[dict] = field(default_factory=list)  # 存储联合主键
    columns: List[ReactColumnMetaInfo]

    # 在初始化时将 CommonColumnMetaInfo 转换为 ReactColumnMetaInfo
    def __post_init__(self):
        # 转换列信息
        self.columns = [
            ReactColumnMetaInfo(
                sql_raw_info=column.sql_raw_info,
                config=column.config
            )
            for column in self.columns
        ]

        # 查找主键列，判断是否为联合主键
        for column in self.columns:
            if column.sql_raw_info.primary_key:  # 检查字段是否为主键
                self.primary_keys.append({
                    'name': camel_case_filter(column.sql_raw_info.name),
                    'type': column.typescript_type_name
                })

        # 如果只有一个主键字段，设置 primary_key_name 和 primary_key_type
        if len(self.primary_keys) == 1:
            self.primary_key_name = camel_case_filter(self.primary_keys[0]['name'])
            self.primary_key_type = self.primary_keys[0]['type']

    def __str__(self) -> str:
        columns_str = "\n".join([str(column) for column in self.columns])
        primary_keys_str = ', '.join([f"{pk['name']}({pk['type']})" for pk in self.primary_keys])
        return (
            f"Table: {self.sql_raw_info.table_name} | "
            f"  Class Name: {self.class_name} | "
            f"  Display Name: {self.chinese_name} | "
            f"  Primary Keys: {primary_keys_str} | "  # 显示联合主键信息
            f"  Primary Key Type: {self.primary_key_type} | "
            f"  Primary Key Name: {self.primary_key_name} | "
            f"  Current Date: {self.current_date} | "  # 继承自父类的字段
            f"  Version: {self.version} | "  # 继承自父类的字段
            f"  Columns:\n{columns_str}"
        )

# 根据 TableInfoSQL 生成 ReactTableMetaInfo 实例的函数
def create_react_meta_info(table_info_sql: TableInfoSQL, config: TableInfoConfig) -> ReactTableMetaInfo:
    # 生成 CommonTableMetaInfo 实例，传递 current_date 和 version
    common_meta_info = create_common_meta_info(table_info_sql, config)

    # 创建 ReactTableMetaInfo 实例
    react_table_meta_info = ReactTableMetaInfo(
        sql_raw_info=common_meta_info.sql_raw_info,
        chinese_name=common_meta_info.chinese_name,
        columns=common_meta_info.columns,  # columns 在 __post_init__ 中会转换为 ReactColumnMetaInfo
        current_date=common_meta_info.current_date,  # 将 current_date 传递给 ReactTableMetaInfo
        version=common_meta_info.version,  # 将 version 传递给 ReactTableMetaInfo

        class_name=common_meta_info.class_name,
        table_name=common_meta_info.table_name,
        entity_name=common_meta_info.entity_name,

        primary_key_name='',  # 默认为空，初始化时设置
        primary_key_type='',  # 默认为空，初始化时设置
    )

    return react_table_meta_info